/* Arquivo fonte retirado do projeto SIGA-RENAPI sob sob Licença Pública Geral GNU,
 * adapatado para satisfazer as necessidades arquiteturais desta aplicação.
 */

package br.edu.ifrn.mb.generic;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import br.edu.ifrn.exception.NegocioException;
import br.edu.ifrn.generic.GenericDAO;
import br.edu.ifrn.generic.GenericEntidade;
import br.edu.ifrn.util.FacesUtil;

public abstract class GenericCrudMB<Entidade extends GenericEntidade > extends GenericMB{

	private Logger logger = Logger.getLogger(this.getClass().getSimpleName());

	protected boolean exibirTodosRegistrosAoPesquisar = false;
	
	protected List<Entidade> dadosPesquisa = new ArrayList<Entidade>();
	
	protected Entidade dadosForm;
	
	protected Class<Entidade> clazzEntidade;
	
	private String whereScope = null;
	
	@SuppressWarnings("unchecked")
	public GenericCrudMB() {
		// obtem o tipo da classe de <T> em tempo de execução
			ParameterizedType parameterizedType = (ParameterizedType) getClass()
					.getGenericSuperclass();
			this.clazzEntidade = (Class<Entidade>) parameterizedType.getActualTypeArguments()[0];

			try {
				this.limparDadosForm();
			} catch (NegocioException e) {
				e.printStackTrace();
			}
	}

	public List<Entidade> getDadosPesquisa() {
		return dadosPesquisa;
	}

	public void setDadosPesquisa(List<Entidade> dadosPesquisa) {
		this.dadosPesquisa = dadosPesquisa;
	}

	public Entidade getDadosForm() {
		return dadosForm;
	}

	public void setDadosForm(Entidade dadosForm) {
		this.dadosForm = dadosForm;
	}
	
	/**
	 * exibe a página de pesquisa
	 * @return
	 */
	public String pesquisar(){
		try {
			pesquisarImpl();
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao realizar a pesquisa: "  + e.getMessage());
		}
		return getPaginaPesquisa();
	}
	
		
	public void limparDadosForm() throws NegocioException{
		try {
			//implementação padrão do metodo limparDadosForm()
			dadosForm = clazzEntidade.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			throw new NegocioException("Erro ao instanciar dinamicamente a classe '" +clazzEntidade.getSimpleName() + "': " + e.getMessage());
		} 
	}

	
	public String getPaginaInclusao(){
		String pag = clazzEntidade.getSimpleName() + "IncluirAlterar";
		logger.info(">>>>pag inclusao: " + pag);
		return pag;
	}
	
	public String getPaginaAlteracao(){
		String pag = getPaginaInclusao();
		logger.info(">>>>pag alteracao: " + pag);
		return pag;
	}
	
	public String getPaginaExclusao(){
		String pag = clazzEntidade.getSimpleName() + "Excluir";
		logger.info(">>>>pag exclusao: " + pag);
		return pag;
	}
	
	public String getPaginaPesquisa(){
		String pag = clazzEntidade.getSimpleName() + "Pesquisar";
		logger.info(">>>>pag pesquisa: " + pag);
		return pag;
	}
	

	/**
	 * exibe pag. inclusão
	 * @return
	 */
	public String exibirInclusao(){
		try{
			limparDadosForm();
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao exibir a inclusão: "  + e.getMessage());
			return null;
		}		
		return getPaginaInclusao();
	}
	/**
	 * exibe pag. pesquisa
	 * @return
	 */
	public String exibirPesquisa(){
		try{
			this.dadosPesquisa = null;
			//se for para exibir todos os registros
			//ao exibir a pagina
			if(exibirTodosRegistrosAoPesquisar){
				return pesquisar();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao exibir a página: "  + e.getMessage());
			return null;
		}		
		return getPaginaPesquisa();
	}
	
	
	/**
	 * inclui no BD
	 * @return
	 */
	public String incluir(){
		try {
			dadosForm.validar();
			incluirImpl();
			FacesUtil.adicionarMensagemAviso("Inclusão realizada com sucesso");
			
		} catch (NegocioException e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro( e.getMensagens() );
			return null;
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao realizar a inclusão: "  + e.getMessage());
			return null;
		}
		return exibirPesquisa();
	}

	/**
	 * exibe pag. alteracao
	 * @return
	 */
	public String exibirAlteracao(){
		try{
			dadosForm = getDao().consultarPorId(dadosForm.getId());
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao exibir a alteração: "  + e.getMessage());
			return null;
		}		
		return getPaginaAlteracao();
	}
	
	/**
	 * altera no BD
	 * @return
	 */
	public String alterar(){
		try {
			dadosForm.validar();
			alterarImpl();
			FacesUtil.adicionarMensagemAviso("Alteração realizada com sucesso");
		} catch (NegocioException e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro( e.getMensagens() );
			return null;
		}  catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao realizar a alteração: "  + e.getMessage());
			return null;
		}
		return exibirPesquisa();
	}
	
	
	/**
	 * exibe pag. exclusão
	 * @return
	 */
	public String exibirExclusao(){
		try {
			dadosForm = getDao().consultarPorId(dadosForm.getId());
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao exibir a exclusão: "  + e.getMessage());
			return null;
		}
		return getPaginaExclusao();
	}
	
	/**
	 * exclui no BD
	 * @return
	 */
	public String excluir(){
		try {
			excluirImpl();
			FacesUtil.adicionarMensagemAviso("Exclusão realizada com sucesso");
			
		} catch (Exception e) {
			e.printStackTrace();
			FacesUtil.adicionarMensagemErro("Erro ao realizar a exclusão: "  + e.getMessage());
			return null;
		}
		return exibirPesquisa();
	}
	
	public abstract String getTitulo();
	
	protected abstract GenericDAO<Entidade> getDao();
	

	public void alterarImpl() throws NegocioException {
		getDao().alterar(dadosForm);
	}

	public void excluirImpl() throws NegocioException {
		getDao().remover(dadosForm.getId());
	}

	public void incluirImpl() throws NegocioException {
		getDao().inserir(dadosForm);
	}

	public void pesquisarImpl() throws NegocioException {
		if(whereScope != null){
			dadosPesquisa = getDao().consultarTodos(whereScope, null);
		}else{
			dadosPesquisa = getDao().consultarTodos();
		}
	}

	public boolean isExibirTodosRegistrosAoPesquisar() {
		return exibirTodosRegistrosAoPesquisar;
	}

	public void setExibirTodosRegistrosAoPesquisar(
			boolean exibirTodosRegistrosAoPesquisar) {
		this.exibirTodosRegistrosAoPesquisar = exibirTodosRegistrosAoPesquisar;
	}

	public void setWhereScope(String whereScope) {
		this.whereScope = whereScope;
	}

	public String getWhereScope() {
		return whereScope;
	}

}
